<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Database\QueryException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Validator;
use App\Models\Api\Files;

/**
 * @group 文件传统一接口
 *
 * 采用 restful api  
 *
 * Body Parameters 表示请求的所需要的参数
 *
 * Query Parameters 表示返回参数的名称
 */
class FilesController extends Controller
{
    /**
     * video 2,image 1,audio 3
     * 请使用post  form-data方式传输图片
     *
     * 返回值
     *
     * 400 参数错误
     * 411 文件处理时发生错误 请联系管理员
     * 500 图片信息存入数据库时发生错误 请联系管理员
     *
     * @bodyParam file file required 传输的文件 请保证文件只能是 minetype中 audio image 类型,不支持->txt等文件
     * @queryParam local_url 文件上传保存在服务器的url
     * @queryParam local_path 文件上传保存在服务器的位置
     * @queryParam remote_url 文件上传保存在远程服务器的url
     * @queryParam tx_url 文件上传保存在腾讯服务器的url
     * @queryParam ali_url 文件上传保存在阿里服务器的url
     * @queryParam qiniu_url 文件上传保存在七牛服务器的url
     * @queryParam type 文件类型 video 2,image 1,audio 3
     * @queryParam storage_domain 文件访问的域名 如果返回的是文件访问的相对路径 可以用来拼接成url访问资源
     */

    public function store(Request $request){
        $this->storage_config = env('FILE_STORE_LOCATION');
        $validator = Validator::make($request->all(), genValidate());
        if($validator->fails()){
            return response()->json($validator->errors()->messages(),400);
        }
        try{
            try {
                $res = $this->fileHandler($request->file('file'),$request);
            }catch (FilesException $e){
                return response()->json($e->getMessage(),411);
            }
            $host = "";
            try {
                $host = $request->getHttpHost();
            }catch (\Exception $e){

            };
            $store_host = $host.'/storage';
            //$res['local_url'] = $store_host.'/'.$res['local_url'];

            $res['storage_domain'] = $store_host;
            return response()->json($res,201);
        }catch (QueryException $e){
            return response()->json($e->getMessage(),500);
        }
    }
    //判断文件类型
    private function detectFileType($file){
        //$fileType = array('video'=>2,'image'=>1,'audio'=>3,'application/octet-stream'=>3);
        $fileType = array('video'=>2,'image'=>1);
        try {
            $type = $file->getClientMimeType();
        }catch (\Exception $e){
            throw new FilesException('文件mime格式无法读取');
        }
        $type_num = 0;
        foreach ($fileType as $k=>$v){
            if(strpos($type,$k) === 0){
               $type_num = $v;
               break;
            }
        }

        return $type_num;
    }
    private function fileHandler($file,$request){

        try {
            $ext = $file->getClientOriginalExtension();//获取上传文件的后缀 好像是从文件二进制代码中判断的
        }catch (\Exception $e){
            throw new FilesException('系统无法读取该文件的文件格式');
        }
        $type = $this->detectFileType($file);//根据文件的格式在自己的数据库中给他归类
        $realPath = $file->getRealPath();
        $dirname = self::getStoreDir();
        $fileuuid = uniqid();
        $filename = $fileuuid.'.'.$ext;
        $fileStorePath = $dirname.DIRECTORY_SEPARATOR.$filename;
        $bool = Storage::disk($this->storage_config)->put($fileStorePath, file_get_contents($realPath));
        if(!$bool){
            //return response()->json(encodeMsg(["message"=>"文件存储失败 请联系管理员"],500),500);
            throw new FilesException('文件存储失败');
        }
        $file = new Files();//test
        $file->local_url=$fileStorePath;
        $file->local_path=self::getLocalFileDir().DIRECTORY_SEPARATOR.$fileStorePath;//图片存储在本地的位置
        $file->type=$type;
        $file->remote_url = 'null';
        $file->tx_url = 'null';
        $file->ali_url = 'null';
        $file->qiniu_url = 'null';
        //用户
        //$user = auth()->user();
        try{
            $user_id = $request->user_id;
            $user_type = $request->user_type;
            $file->user_id = $user_id;
            $file->upload_user_type = $user_type;
        }catch (\Exception $e)
        {

        }
        $file->save();
        return $file->toArray();
    }

    //获取当前文件存储的顶层文件夹
    private function getLocalFileDir()
    {
        $file_basedir = config("filesystems.disks.{$this->storage_config}.root");
        return $file_basedir;
    }

    //返回图片存储文件夹的相对路径  在系统的中的绝对路径中创建这个文件夹
    private function getStoreDir()
    {
        $store_dirname = date('Y-m-d');//获取当前时间
        $dirname = self::getLocalFileDir().DIRECTORY_SEPARATOR.$store_dirname;//把当前的天和图片存储顶层文件夹拼接起来 作为文件夹
        if(!is_dir($dirname)){
            mkdir($dirname);
        }
        return $store_dirname;
    }

}